#pragma once
#include <iostream>
#include <typeinfo>
#include <cassert>

class Any
{
private:
    class Holder
    {
    public:
        Holder() {}
        ~Holder() {}
        virtual const std::type_info &Type() = 0;
        virtual Holder *Clone() = 0;
    };

    template <class T>
    class PlaceHolder : public Holder
    {
    public:
        PlaceHolder() {}
        PlaceHolder(const T &val) : _val(val) {}
        ~PlaceHolder() {}
        virtual const std::type_info &Type() { return typeid(T); }
        virtual Holder *Clone() { return new PlaceHolder(_val); }
        T _val;
    };

    Holder *_holder;

public:
    Any() : _holder(nullptr) {}
    template <class T>
    Any(const T &val) : _holder(new PlaceHolder<T>(val)) {}
    Any(const Any &other) : _holder(other._holder ? other._holder->Clone() : nullptr) {}
    ~Any() { delete _holder; }

    Any &Swap(Any &other)
    {
        std::swap(_holder, other._holder);
        return *this;
    }

    template <class T>
    T *Get()
    {
        assert(typeid(T) == _holder->Type());
        return &((PlaceHolder<T> *)_holder)->_val;
    }

    template <class T>
    Any &operator=(const T &val)
    {
        Any(val).Swap(*this);
        return *this;
    }

    Any &operator=(Any &other)
    {
        Any(other).Swap(*this);
        return *this;
    }
};